package com.coincalf.web;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.plugins.Page;
import com.coincalf.chan.feign.MessagingServiceClient;
import com.coincalf.dto.*;
import com.coincalf.entity.EntrustOrder;
import com.coincalf.entity.Market;
import com.coincalf.framework.constants.Constant;
import com.coincalf.framework.exception.GlobalDefaultException;
import com.coincalf.framework.http.Response;
import com.coincalf.service.EntrustOrderService;
import com.coincalf.service.MarketService;
import com.coincalf.service.TurnoverOrderService;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

/**
 * @Description: 币币交易订单 controller
 * @Author: Chen Long
 * @Date: Created in 2018/5/14 下午8:00
 * @Modified by: Chen Long
 */
@RestController
@RequestMapping("/trade/order")
@Slf4j
@Api(value = "币币交易订单", description = "币币交易订单 REST API")
public class TradeOrderController implements Constant {

    @Autowired
    private TurnoverOrderService turnoverOrderService;
    @Autowired
    private EntrustOrderService entrustOrderService;
    @Autowired
    private MarketService marketService;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private MessagingServiceClient messagingServiceClient;
    @Autowired
    private CommonController commonController;

    /**
     * 币币交易委托下单
     *
     * @param order 委托下单请求参数
     * @return
     */
    //@PreAuthorize("isAuthenticated()")
    @PostMapping("/entrusts")
    @ApiOperation(value = "ORDER-001 币币交易委托下单", notes = "币币交易委托下单", httpMethod = "POST")
    @ApiImplicitParam(name = "order", value = "币币交易委托下单请求参数", required = true, dataType = "CreateTradeOrderDTO", paramType = "body")
    @ResponseBody
    public Object createEntrustOrder(
            HttpServletRequest request,
            @RequestBody @Valid CreateTradeOrderDTO order
    ) {
        Long userId = commonController.getUserId(request);
        Market market = marketService.queryBySymbol(order.getSymbol());
        if (market == null) {
            log.error("交易市场错误");
            throw new GlobalDefaultException(50002);
        }
        Response response = entrustOrderService.createEntrustOrder(market, order, userId);
        if (response.getData() == null) {
            return response;
        }
        long orderId = Long.parseLong(response.getData().toString());
        // 将委托订单加入撮合队列
        String redisKey = new StringBuffer(REDIS_KEY_TRADE_MATCH).append(order.getSymbol()).toString();
        redisTemplate.opsForList().rightPush(redisKey, String.valueOf(orderId));
        // 更新委托队列-默认合并深度
        entrustOrderService.DEPTH_CACHE_INSTANCE().refresh(market.getId());
        // 更新委托队列-合并深度1
        entrustOrderService.MERGE_LOW_DEPTH_CACHE_INSTANCE().refresh(market.getId());
        // 更新委托队列-合并深度2
        entrustOrderService.MERGE_HIGH_DEPTH_CACHE_INSTANCE().refresh(market.getId());
        // 推送用户未成交委托
        JSONObject body = new JSONObject();
        body.put("symbol", order.getSymbol());
        messagingServiceClient.convertAndSendToUser(Constant.CH_ORDER_PENDING, String.valueOf(userId), body.toJSONString());
        return Response.ok();
    }

    /**
     * 撤销委托
     *
     * @param orderId 订单号
     * @return
     */
    //@PreAuthorize("isAuthenticated()")
    @DeleteMapping("/entrusts/{orderId}")
    @ApiOperation(value = "ORDER-002 币币交易撤销委托", notes = "币币交易撤销委托", httpMethod = "DELETE")
    @ApiImplicitParam(name = "orderId", value = "币币交易委托订单号", required = true, dataType = "long", paramType = "path")
    @ResponseBody
    public Object cancelEntrustOrder(HttpServletRequest request, @PathVariable("orderId") long orderId) {
        Long userId = commonController.getUserId(request);
        Market market = entrustOrderService.cancelEntrustOrder(orderId, userId);
        // 更新委托队列
        entrustOrderService.DEPTH_CACHE_INSTANCE().refresh(market.getId());
        // 推送用户未成交委托
        JSONObject body = new JSONObject();
        body.put("symbol", market.getSymbol());
        messagingServiceClient.convertAndSendToUser(Constant.CH_ORDER_PENDING, String.valueOf(userId), body.toJSONString());
        messagingServiceClient.convertAndSendToUser(Constant.CH_ORDER_FINISHED, String.valueOf(userId), body.toJSONString());
        return Response.ok();
    }

    /**
     * 查询未完成委托
     *
     * @param symbol  交易对标识符
     * @param size    每页显示数据量
     * @param current 当前页码
     * @return
     */
    //@PreAuthorize("isAuthenticated()")
    @GetMapping("/entrusts/{symbol}/{current}/{size}")
    @ApiOperation(value = "ORDER-003 币币交易未完成委托订单", notes = "币币交易未完成委托订单", httpMethod = "GET")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "symbol", value = "交易对标识符", required = true, dataType = "String", paramType = "path"),
            @ApiImplicitParam(name = "current", value = "当前页码", required = true, dataType = "int", paramType = "path"),
            @ApiImplicitParam(name = "size", value = "每页显示数据量", required = true, dataType = "int", paramType = "path")
    })
    @ResponseBody
    public Object entrustOrder(
            HttpServletRequest request,
            @PathVariable("symbol") String symbol,
            @PathVariable("current") int current,
            @PathVariable("size") int size
    ) {
        Long userId = commonController.getUserId(request);
        Page<EntrustOrder> page = new Page<>();
        page.setCurrent(current).setSize(size);
        Page<TradeEntrustOrderDTO> entrustOrderList = entrustOrderService.queryEntrustOrder(symbol, userId, page);
        return Response.ok(entrustOrderList);
    }

    /**
     * 查询历史委托
     *
     * @param symbol  交易对标识符
     * @param size    每页显示数据量
     * @param current 当前页码
     * @return
     */
    //@PreAuthorize("isAuthenticated()")
    @GetMapping("/history/{symbol}/{current}/{size}")
    @ApiOperation(value = "ORDER-004 币币交易历史委托订单", notes = "币币交易历史委托订单", httpMethod = "GET")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "symbol", value = "交易对标识符", required = true, dataType = "String", paramType = "path"),
            @ApiImplicitParam(name = "current", value = "当前页码", required = true, dataType = "int", paramType = "path"),
            @ApiImplicitParam(name = "size", value = "每页显示数据量", required = true, dataType = "int", paramType = "path")
    })
    @ResponseBody
    public Object historyOrder(
            HttpServletRequest request,
            @PathVariable("symbol") String symbol,
            @PathVariable("current") int current,
            @PathVariable("size") int size
    ) {
        Long userId = commonController.getUserId(request);
        Page<EntrustOrder> page = new Page<>();
        page.setCurrent(current).setSize(size);
        Page<TradeEntrustOrderDTO> entrustOrderList = entrustOrderService.queryHistoryEntrustOrder(symbol, userId, page);
        return Response.ok(entrustOrderList);
    }

    /******************************************** 微服务 ****************************************************/
    /**
     * 查询成交数据（微服务）
     *
     * @param marketId 交易对ID
     * @return
     */
    @ApiIgnore
    @GetMapping("/turnover/{marketId}")
    public TurnoverDataDTO turnoverData(@PathVariable("marketId") long marketId) {
        return turnoverOrderService.queryAndSaveTurnoverData(marketId);
    }

}
